package comp6231.project.replica.kelvin;

import comp6231.project.common.ReplicaState;

/**
 * Class to handle main logic of retail store
 * @author Kelvin Iu
 *
 */
public class StoreLogic {

	private RemoteRetailStoreServer remoteServer;
	private ItemsList items = new ItemsList();
	private CustomerRecords customerRecords = new CustomerRecords();
	
	public void init(String itemsList, String storageDir, RemoteRetailStoreServer remoteServer) {
		items.load(itemsList);
		System.out.println(items);
		
		customerRecords.setStorageDir(storageDir);
		
		this.remoteServer = remoteServer;
	}
	
	public int buyOp(String customerID, String itemID, int numberOfItem) {
		System.out.println("buyOp: customerID=" + customerID + ", itemID=" + itemID + ", numberOfItem=" + numberOfItem);
		int result = buyOpInternal(customerID, itemID, numberOfItem);
		String[] otherServers = remoteServer.getOtherStoreNames();
		if (result == 0 && otherServers != null) {
			for (int i = 0; i < otherServers.length; i++) {
				System.out.println("buyOp: Buying from server " + otherServers[i]);
				result = remoteServer.buyFromServer(otherServers[i], customerID, itemID, numberOfItem);
				if (result != 0) {
					break;
				}
			}
		}
		System.out.println("buyOp: result=" + result);
		debug();
		return result;
	}

	public int returnOp(String customerID, String itemID, int numberOfItem) {
		System.out.println("returnOp: customerID=" + customerID + ", itemID=" + itemID + ", numberOfItem=" + numberOfItem);
		int result = 0;
		if (customerRecords.addReturnRecord(customerID, itemID, numberOfItem)) {
			items.lock(itemID);
			items.setCount(itemID, items.getCount(itemID) + numberOfItem);
			items.unlock(itemID);
			result = numberOfItem;
		}
		System.out.println("returnOp: result=" + result);
		debug();
		return result;
	}
	
	public int checkStockOp(String itemID) {
		System.out.println("checkStockOp: itemID=" + itemID);
		int count = checkStockOpInternal(itemID);
		count += remoteServer.checkStockFromOtherServers(itemID);
		System.out.println("checkStockOp: result=" + count);
		return count;
	}
	
	public int exchangeOp(String customerID, String boughtItemID,
			int boughtNumber, String desiredItemID, int desiredNumber) {
		System.out.println("exchangeOp: customerID=" + customerID + ", boughtItemID=" + boughtItemID + ", boughtNumber=" + boughtNumber + ", desiredItemID=" + desiredItemID + ", desiredNumber=" + desiredNumber);
		int result = 0;
		items.lockBoth(boughtItemID, desiredItemID);
		if ( customerRecords.getNumOfItemBought(customerID, boughtItemID) >= boughtNumber &&
			 items.getCount(desiredItemID) >= desiredNumber ) {
			returnOp(customerID, boughtItemID, boughtNumber);
			buyOpInternal(customerID, desiredItemID, desiredNumber);
			result = desiredNumber;
		}
		items.unlock(boughtItemID);
		items.unlock(desiredItemID);
		System.out.println("exchangeOp: result=" + result);
		return result;
	}
	
	public int buyOpInternal(String customerID, String itemID, int numberOfItem) {
		System.out.println("buyOpInternal: customerID=" + customerID + ", itemID=" + itemID + ", numberOfItem=" + numberOfItem);
		int result = numberOfItem;
		items.lock(itemID);
		if (items.getCount(itemID) < numberOfItem) {
			result = 0;
		}
		if (result != 0) {
			items.setCount(itemID, items.getCount(itemID) - numberOfItem);
			customerRecords.addSaleRecord(customerID, itemID, numberOfItem);
		}
		items.unlock(itemID);
		System.out.println("buyOpInternal: result=" + result);
		debug();
		return numberOfItem;		
	}
	
	public int checkStockOpInternal(String itemID) {
		System.out.println("checkStockOpInternal: itemID=" + itemID);
		int count = items.getCount(itemID);
		System.out.println("checkStockOpInternal: result=" + count);
		return count;
	}
	
	private void debug() {
		System.out.println(items);
		System.out.println(customerRecords);
	}	
	
	public void transferToStoreState(ReplicaState state) {
		items.transferToStoreState(state);
		customerRecords.transferToStoreState(state);		
	}
	
	public void transferFromStoreState(ReplicaState state) {
		items.transferFromStoreState(state);
		customerRecords.transferFromStoreState(state);	
		System.out.println("=== transferFromStoreState");
		System.out.println(items);
		System.out.println(customerRecords);
	}
}
